let platform = 'web'
let datasource = 3     //1、ios-app  2、andriod-app  3、web（网站）
const onceMap = {}
const jsBridge = {
  /**
   * 在原生控制台打印日志
   * param msg String[] 日志信息
   */
  log(msg) {
    return jsBridge.callBridge('log', {
      msg: JSON.stringify({type: Object.prototype.toString.call(msg), msg})
    })
  },
  /**
   * 网络请求模块
   * param url String 请求地址，如果请求地址已http://或者https://开头，直接发送请求，
   *                  如果以/开头，会在前添加API_HOST的值
   *                  其他的开头，会在前添加API_HOST/customer/
   * param data Object 请求参数，key-value键值对
   * param options optionsObject 附加设置，会覆盖掉默认设置
   * optionsObject method String 请求方式 POST、GET
   *
   */
  http(url, data = {}, options = {}) {
    // jsBridge.log('data='+data)
    // alert('data='+JSON.stringify(data))
    return jsBridge.callBridge('http', {
      url, data, options
    })
  },
  /**
   * 打开新的窗口，完整web网页直接打开，否则按照本地资源处理，相对路径，参数使用？方式连接在后面（get传参方式）
   * param url  String url地址
   * param noBar  Boolean 是否有标题栏，true：有(不传默认该值)；false：无
   * param type  1：打开本地连接 2：打开外部链接 3：打开pdf 4：浏览器打开
   * param params Object 需要带到下个页面的参数
   * param replace Boolean 是否替换当前页面
   * return null
   **/
  openWindow(url, params = {}, options = {}) {
    return jsBridge.callBridge('openWindow', {
      ...options, params, url
    }, true)
  },
  //返回原生界面
  openHome(data) {
    return jsBridge.callBridge('openHome', data, true)
  },
  //通知原生刷新
  updateStatus(data) {
    return jsBridge.callBridge('updateStatus', data)
  },
  /**
   * 关闭当前activity
   * return null
   **/
  closeWindows() {
    return jsBridge.callBridge('closeWindows', {}, true)
  },
  /**
   * 为当前activity设置标题
   * param title  String 标题
   * return null
   **/
  setTitle(title) {
    return jsBridge.callBridge('setTitle', {title})
  },
  /**
   * 登录方法
   * param password  String 密码
   * param phoneNum  String 手机号
   * return 用户信息或错误信息
   **/
  // login(data) {
  //   return jsBridge.callBridge('login', data)
  // },
  /**
   * 登出方法
   **/
  // logout(data) {
  //   return jsBridge.callBridge('logout', data)
  // },
  /**
   * 向缓存中写入数据，K-V形式
   * param key  String key
   * param value  Any 值
   * return data
   **/
  // setData(key, value) {
  //   return jsBridge.callBridge('setData', {key, value: JSON.stringify(value)}).then(v => v && JSON.parse(v))
  // },
  setData(key, value) {
    return jsBridge.callBridge('setData', {key, value})
  },
  /**
   * 从缓存中获取数据，K-V形式
   * param key  String key
   * return value
   **/
  // getData(key) {
  //   return jsBridge.callBridge('getData', {key}).then(v => v && JSON.parse(v))
  // },
  getData(key) {
    return jsBridge.callBridge('getData', {key})
  },

  /**
   * 调用原生选择弹框
   * 返回用户最终选择的code
   * 详见yapi-jt2 App-公共分类-【原生】选择弹窗
   **/
  alertChoose(data) {
    return jsBridge.callBridge('alertChoose', data, true)
  },

  /**
   * 删除缓存
   * param key  String key
   * return null
   **/
  delData(key) {
    return jsBridge.callBridge('delData', {key}, true)
  },
  /**
   * 清空缓存
   */
  clearData() {
    return jsBridge.callBridge('clearData', {}, true)
  },
  /**
   * 返回上一页，如果该webView里打开多层页面，先逐一关闭页面，没有多层页面，则关闭当前activity
   * param data Object 需要回传给上个页面的参数
   **/
  goBack(data) {
    return jsBridge.callBridge('goBack', data, true)
  },
  /**
   * 是否允许页面缩放，普通页面禁止缩放，需要缩放的页面调用该方法打开缩放
   **/
  allowZoom() {
    return jsBridge.callBridge('allowZoom', {}, true)
  },
  /**
   * 弹出消息通知
   * param msg  String 消息内容
   **/
  toast(msg) {
    return jsBridge.callBridge('toast', {msg})
  },
  /**
   * 修改状态栏字体颜色
   * param type jsBridge.Color Dark：黑色字体；Light：白色字体（默认）
   **/
  Color: {Dark: 'Dark', Light: 'Light'},
  setStatusBarFontColor(type) {
    return jsBridge.callBridge('setStatusBarFontColor', {type})
  },
  /**
   * 获取系统信息
   * return {
   *   statusBarHeight Number 状态栏高度
   *   driveId String 设备ID
   *   version String 版本号
   * }
   **/
  getSystemConfig() {
    return jsBridge.callBridge('getSystemConfig')
  },
  share(data) {
    return jsBridge.callBridge('share', data)
  },
  showReportDialog(data) {
    return jsBridge.callBridge('showReportDialog', data)
  },
  jump(data) {
    return jsBridge.callBridge('jump', data)
  },
  jumpOrg(data) {
    return jsBridge.callBridge('jumpOrg', data)
  },
  /**
   * 切换tab
   * param page Number 取值0-4，同APP底部菜单的index
   * return null
   **/
  exchangeTabPage(index) {
    return jsBridge.callBridge('exchangeTabPage', {page: index}, true)
  },
  /**
   * 打开原生日期选择器
   * param date String 默认选中的日期，yyyy-MM-dd格式的日期字符串
   * return date String 用户选择的日期，yyyy-MM-dd格式的日期字符串
   */
  nativeCalendar(date) {
    return jsBridge.callBridge('nativeCalendar', {date}, true)
  },


  /**
   * 打开精简研报详情页
   * param infoId String 研报ID
   * param infoType String 研报类型
   */
  openBrsDetail(infoId, infoType) {
    infoType = infoType || '4'
    return jsBridge.callBridge('openBrsDetail', {
      infoId, infoType
    }, true)
  },
  /**
   *
   * @param exchange String 股票类型 eg: SH
   * @param code String 股票代码
   * @return null
   */
  openStock(exchange, code) {
    return jsBridge.callBridge('openStock', {
      exchange, code
    }, true)
  },
  /**
   * 打开登录
   */
  openLogin: () => jsBridge.callBridge('openLogin', {}, true),
  /**
   * 退出登录
   */
  logOut: () => jsBridge.callBridge('logOut', {}, true),
  /**
   * 打开资讯语音
   * @param data
   */
  openInfoVoice(data) {
    return jsBridge.callBridge('openInfoVoice', data, true)
  },
  /**
   * 打开首页
   * @param data 参数对象
   * @param data pageUrl 页面文件名 如：  native/index-data.html
   * @param data method 页面内调用方法名
   * @returns {*}
   */
  openIndexPage(data) {
    return jsBridge.callBridge('openIndexPage', data, true)
  },
  /**
   * 打开拨号
   * @param phone 手机号码
   */
  openCallPhone(phone) {
    return jsBridge.callBridge('openCallPhone', {phone: phone}, true)
  },
  /**
   * 关闭资讯语音
   */
  closeInfoVoice() {
    return jsBridge.callBridge('closeInfoVoice', {}, true)
  },
  /**
   * 打开视频（直播、录播）
   * resourceType为2的时候是录播
   */
  openVideo(data) {
    return jsBridge.callBridge('openVideo', data, true)
  },
  /**
   * 复制功能,传文字 word
   */
  copyWord(data) {
    return jsBridge.callBridge('copyWord', data, true)
  },
  /**
   * 获取当前正在播放的音频信息
   * @returns
   *   id: String 当前正在播放的音频Id
   *   type: String 当前正在播放的音频类型
   */
  getPlayingItem() {
    return jsBridge.callBridge('getPlayingItem', {}, true)
  },
  /**
   * 用户点击资讯详情后将该资讯标为已阅读
   */
  setInfoRead(data) {
    return jsBridge.callBridge('setInfoRead', data, true)
  },
  /**
   * 跳转到系统消息接收设置页面
   */
  setSysMsgOpen() {
    return jsBridge.callBridge('setSysMsgOpen', {}, true)
  },
  /**
   * 获取资讯与公告总体阅读状态
   */
  getMsgReadStatus() {
    return jsBridge.callBridge('getMsgReadStatus', {}, true)
  },
  /**
   * 获取当前用户的消息接收状态
   */
  getSysMsgState() {
    return jsBridge.callBridge('getSysMsgState', {}, true)
  },
  /**
   * 关闭公告弹窗
   */
  closeNoticeAlert() {
    return jsBridge.callBridge('closeNoticeAlert', {}, true)
  },
  /**
   * 用户点击公告详情后将该公告标为已阅读
   */
  setSysNoticeRead(noticeId) {
    return jsBridge.callBridge('setSysNoticeRead', {noticeId}, true)
  },
  /**
   * 获取当前缓存大小
   */
  getCache() {
    return jsBridge.callBridge('getCache', {}, true)
  },
  /**
   * 清除缓存
   */
  clearCache() {
    return jsBridge.callBridge('clearCache', {}, true)
  },
  /**
   * 打开pdf
   * @param url pdf连接
   * @param title pdf标题
   */
  openPdf(url, title) {
    return jsBridge.callBridge('openPdf', {url, title}, true)
  },
  /**
   * 获取当前播放的音频
   */
  getCurrentVoice(){
    return jsBridge.callBridge('getCurrentVoice', {}, true)
  },
  //设置全屏
  setWebFullScreen(data){
    return jsBridge.callBridge('setWebFullScreen', data, true)
  },
  //获取股票本地原生缓存
  getAllStockAttStatus(){
    return jsBridge.callBridge('getAllStockAttStatus', {}, true)
  },
  //设置股票本地原生缓存
  setStockAttStatus(data){
    return jsBridge.callBridge('setStockAttStatus', data, true)
  },
  /**
   * 获取图片列表
   */
  getImgList(data) {
    return jsBridge.callBridge('getImgList', data, true)
  },

  /**
    * 跳转外部浏览器
    */
  goToEnclosure(data) {
    return jsBridge.callBridge('goToEnclosure', data, true)
  },
  /**
   * 跳转机构详情页
   */
  goToOrgPage(data) {
    return jsBridge.callBridge('goToOrgPage', data, true)
  }
}

const bridgeUtils = {
  dealParam(query) {
    const params = {}
    /*如果没用传参数，尝试从url上获取*/
    query = query || window.location.hash || window.location.search
    if (query) {/*如果有参数，把参数转为Object*/
      query = decodeURI(query.indexOf('?') === 0 ? query.substr(1) : query)/*去除？*/
      const str = query.split('&')
      str.forEach(it => {
        const s = it.split('=')
        params[s[0]] = s[1]
      })
    }
    return params
  },
  //生成回调方法，并挂载到window对象上
  addCallBack(resolve, reject, funcName, once) {
    const execFuncName = () => `${funcName}_${Date.now()}_${Math.ceil(Math.random() * 100000)}`
    //通过循环防止出现相同的回调方法名
    let callBack = execFuncName()
    while (window[callBack]) {//如果这个回调方法名已经存在，就会重新生成方法名
      callBack = execFuncName()
    }

    // 该回调方法要是30秒内还未执行，就直接标注为超时了
    const timer = setTimeout(() => {
      window[callBack](false, {'data': '执行超时'})
    }, dict.METHOD_TIMEOUT)

    window[callBack] = (isSuccess, data) => {
      clearTimeout(timer)//方法执行后清除定时器
      once && delete onceMap[funcName] //移除方法执行中的标记
      if (isSuccess) {
        //如果有返回，触发完成状态
        resolve(data.data)
      } else {
        //否则触发失败状态
        reject(data)
      }
      delete window[callBack]/*移除回调函数*/
    }

    return callBack
  },
  //处理参数，将参数转为URL形式传递给原生
  beforeOpenWindow(data = {}) {
    let {url, params} = data
    if (params) {
      const p = []
      Object.keys(params).forEach(function (key) {
        p.push(key + '=' + params[key])
      })
      if (p.length > 0) {
        url.indexOf('?') > 0 ? url += '&' + p.join('&') : url += '?' + p.join('&')
      }
    }
    delete data.params
    data.url = url
  },
  execBridge(funcName, data, once, getPromise) {
    if (once && onceMap[funcName]) {//如果方法仅存在一个实例并且正在执行中
      return onceMap[funcName]
    } else {
      const promise = getPromise()
      if (once) {
        onceMap[funcName] = promise
      }
      return promise
    }
  },
  loadCss: function (src) {
    const addFile = document.createElement('link')
    addFile.type = 'text/css'
    addFile.rel = 'stylesheet'
    addFile.media = 'screen'
    addFile.href = src
    document.body.appendChild(addFile)
  },
  loadTheme: function () {
    if (platform !== 'web') {
      if (window.systemConfig.themeType === '1' || window.systemConfig.themeType === 1) {
        bridgeUtils.loadCss('../../css/theme/default/black.css')
        // bridgeUtils.loadCss('../css/theme/default/black.css')
      } else {
        bridgeUtils.loadCss('../../css/theme/white/white.css')
        // bridgeUtils.loadCss('../css/theme/white/white.css')
      }
    }
  }
}

/*native回调方法，会触发每个页面的initPage方法*/
function onInit(query) {
  Promise.all([
    jsBridge.getData(dict.CACHE_USER),
    jsBridge.getSystemConfig()
  ]).then(([user, config]) => {
    jsBridge.log(['onInit', user])
    window.systemConfig = config || {}
    window.user = user || defaultUser
    bridgeUtils.loadTheme()

    window.initApi && window.initApi()
    if(datasource === 1 && window.systemConfig.isQingMing){
      $('html').css({'-webkit-filter':'grayscale(100%)','-moz-filter':'grayscale(100%)','!*-ms-filter':'grayscale(100%)','-o-filter':'grayscale(100%)','filter':'progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)','_filter':'none'})
    }

    const params = bridgeUtils.dealParam(query)
    window.initPage && window.initPage(params)
  }).catch(err => jsBridge.log(['onInit error', err.toString()]))
}

function onPause() {
  window.pausePage && window.pausePage()
}

/*页面所在窗口由后台前台时触发的方法*/
function onStart(query = {}) {
  const params = query.params || {}
  jsBridge.getData(dict.CACHE_USER).then(user => {
    jsBridge.log(['onStart', user])
    window.user = user || defaultUser
    window.startPage && window.startPage(params)
  })
}

function onReload() {
  jsBridge.getData(dict.CACHE_USER).then(user => {
    jsBridge.log(['onReload', user])
    window.user = user || defaultUser
    window.reLoadPage && window.reLoadPage()
  })
  // jsBridge.getData('token').then(res => {
  //   // jsBridge.log(['onReload', user])
  //   window.token = res
  //   window.reLoadPage && window.reLoadPage()
  // })
}

if (window.android) {
  platform = 'android'
  datasource = 2
  jsBridge.callBridge = (funcName, data = {}, once = false) =>
    bridgeUtils.execBridge(funcName, data, once, () =>
      new Promise(((resolve, reject) => {
        if (funcName === 'openWindow') {
          bridgeUtils.beforeOpenWindow(data)
        }
        // 如果是执行数据存储，需要对值进行预转义
        // if (funcName === 'setData' && data.value) {
        //   data.value = data.value.replace(/"/g, '\\"')
        // }
        const cbName = bridgeUtils.addCallBack(resolve, reject, funcName, once),
          _data = data ? JSON.stringify(data) : ''
        window.android[funcName] && window.android[funcName](cbName, _data)
      })))
} else if (window.webkit) {
  platform = 'ios'
  datasource = 1
  jsBridge.callBridge = (funcName, data = {}, once = false) =>
    bridgeUtils.execBridge(funcName, data, once, () =>
      new Promise((resolve, reject) => {
        if (funcName === 'openWindow') {
          bridgeUtils.beforeOpenWindow(data)
          // const {url} = data
          // data.url = 'html_files/' + url.split('.html')[0]
          // data.parameter = url.split('.html?')[1]
        }
        data.callBack = bridgeUtils.addCallBack(resolve, reject, funcName, once)
        window.webkit.messageHandlers[funcName].postMessage(data)
      }))
} else {
  // jsBridge.callBridge = (funcName, data, once = false) => new Promise((resolve, reject) => {
  //   console.log(funcName)
  //   web[funcName](data, resolve, reject)
  // })
  jsBridge.callBridge = (funcName, data = {}, once = false) =>
    bridgeUtils.execBridge(funcName, data, once, () =>
      new Promise((resolve, reject) => {
        const callBack = bridgeUtils.addCallBack(resolve, reject, funcName, once)
        // jsBridge.log(funcName, callBack, data)
        // web[funcName](data, resolve, reject)
        web[funcName](data, data => {
          window[callBack](true, {data})
        }, error => {
          window[callBack](false, error)
        })
      })
    )

  const o = document.createElement('script')
  o.src = `${dict.ROOT_PATH()}js/web.js`
  o.type = 'text/javascript'
  o.async = true
  document.body.appendChild(o)
  o.onload = () => {
    /*如果当前页面是web的话，触发页面初始化方法*/
    $(function () {
      /*参数使用K-V形式传递*/
      window.onInit()
    })
  }
}
